/**
 * YAML 模板解析工具
 * 负责解析带标记的 YAML、路径提取、双向数据转换
 */

import yaml from 'js-yaml';

/**
 * 解析 YAML 中的交互标记
 * 格式: `zh:中文名称. type: input. desc: 描述`
 * @param {string} line - YAML 文件的一行
 * @returns {Object|null} 解析结果 { zh, type, desc, options, defaultValue }
 */
export function parseFieldAnnotation(line) {
  const match = line.match(/`([^`]+)`/);
  if (!match) return null;

  const annotation = match[1];
  const result = {};

  // 解析 zh (中文标签)
  const zhMatch = annotation.match(/zh:\s*([^.]+)/);
  if (zhMatch) {
    result.zh = zhMatch[1].trim();
  }

  // 解析 type
  const typeMatch = annotation.match(/type:\s*([^.\[]+)/);
  if (typeMatch) {
    result.type = typeMatch[1].trim();
  }

  // 解析 desc
  const descMatch = annotation.match(/desc:\s*([^.]+)/);
  if (descMatch) {
    result.desc = descMatch[1].trim();
  }

  // 解析 radio button 的选项
  // 格式: type: radio button [value1, value2] [label1, label2] 默认 value 描述
  if (result.type && result.type.includes('radio button')) {
    result.type = 'radio';

    const optionsMatch = annotation.match(/\[([^\]]+)\]\s*\[([^\]]+)\]/);
    if (optionsMatch) {
      const values = optionsMatch[1].split(',').map(v => v.trim().replace(/'/g, ''));
      const labels = optionsMatch[2].split(',').map(l => l.trim());
      result.options = values.map((value, index) => ({
        value,
        label: labels[index] || value,
      }));
    }

    // 解析默认值
    const defaultMatch = annotation.match(/默认\s+\w+\s+(.+?)(?:\s|$)/);
    if (defaultMatch) {
      result.defaultValue = defaultMatch[1].trim();
    }
  }

  return result;
}

/**
 * 根据路径从对象中获取值
 * 支持点号路径和数组索引: 'config.outputs[0].obsUrl'
 * @param {Object} obj - 数据对象
 * @param {string} path - 路径字符串
 * @returns {*} 值
 */
export function getValueByPath(obj, path) {
  const keys = path.split(/\.|\[|\]/).filter(Boolean);
  let result = obj;

  for (const key of keys) {
    if (result === undefined || result === null) {
      return undefined;
    }
    result = result[key];
  }

  return result;
}

/**
 * 根据路径设置对象的值
 * 支持点号路径和数组索引: 'config.outputs[0].obsUrl'
 * @param {Object} obj - 数据对象
 * @param {string} path - 路径字符串
 * @param {*} value - 要设置的值
 */
export function setValueByPath(obj, path, value) {
  // 检查 obj 是否是有效的对象
  if (typeof obj !== 'object' || obj === null) {
    throw new Error(`setValueByPath: 第一个参数必须是对象，当前类型: ${typeof obj}`);
  }

  const keys = path.split(/\.|\[|\]/).filter(Boolean);
  let current = obj;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    const nextKey = keys[i + 1];

    // 检查 current 是否是对象类型
    if (typeof current !== 'object' || current === null) {
      throw new Error(
        `setValueByPath: 路径 "${path}" 中的 "${key}" 不是对象，无法设置子属性。当前值类型: ${typeof current}`
      );
    }

    if (current[key] === undefined || current[key] === null) {
      // 如果下一个 key 是数字，创建数组，否则创建对象
      current[key] = /^\d+$/.test(nextKey) ? [] : {};
    }

    current = current[key];
  }

  // 最后检查
  if (typeof current !== 'object' || current === null) {
    throw new Error(
      `setValueByPath: 无法在非对象类型上设置属性。路径: "${path}"，当前值类型: ${typeof current}`
    );
  }

  current[keys[keys.length - 1]] = value;
}

/**
 * 从 YAML 字符串中移除所有标记（`` 包含的内容）
 * @param {string} yamlContent - YAML 内容
 * @returns {string} 清理后的 YAML 内容
 */
export function removeAnnotations(yamlContent) {
  // 类型检查：确保输入是字符串
  if (typeof yamlContent !== 'string') {
    console.error('removeAnnotations: 参数必须是字符串类型，当前类型:', typeof yamlContent, '值:', yamlContent);
    throw new TypeError(`removeAnnotations expects a string, but received ${typeof yamlContent}`);
  }
  return yamlContent.replace(/\s*`[^`]+`/g, '');
}

/**
 * 解析 YAML 字符串为 JavaScript 对象（自动移除标记）
 * @param {string} yamlContent - YAML 内容
 * @returns {Object} 解析后的对象
 */
export function parseYaml(yamlContent) {
  const cleanedYaml = removeAnnotations(yamlContent);
  return yaml.load(cleanedYaml);
}

/**
 * 将 JavaScript 对象转换为 YAML 字符串
 * @param {Object} obj - JavaScript 对象
 * @returns {string} YAML 字符串
 */
export function stringifyYaml(obj) {
  return yaml.dump(obj, {
    indent: 2,
    lineWidth: -1, // 禁用自动换行
    noRefs: true,
    sortKeys: false,
  });
}

/**
 * 从表单数据构建完整的 YAML 对象
 * @param {Object} formData - 表单数据（扁平化的键值对）
 * @param {Object} originalData - 原始完整数据（包含非交互字段）
 * @param {Array} fieldsConfig - 字段配置
 * @returns {Object} 完整的数据对象
 */
export function buildYamlFromForm(formData, originalData, fieldsConfig) {
  // 检查 originalData 是否有效
  if (!originalData || typeof originalData !== 'object') {
    console.warn('buildYamlFromForm: originalData 无效，使用空对象');
    originalData = {};
  }

  // 深拷贝原始数据，保留非交互字段
  const result = JSON.parse(JSON.stringify(originalData));

  // 遍历所有字段配置，将表单数据写入对应路径
  fieldsConfig.forEach(group => {
    group.fields.forEach(field => {
      const value = formData[field.path];

      if (value !== undefined) {
        // 特殊处理split-path-input类型：合并前缀和用户输入为完整路径
        if (field.type === 'split-path-input' && field.prefixPath && field.fullPath) {
          const prefix = formData[field.prefixPath] || '';
          const userInput = value || '';

          // 构建完整路径: /{bucket_name}/{user_path}
          const cleanPrefix = prefix.replace(/\/$/, ''); // 移除前缀末尾的斜杠
          const cleanUserInput = userInput.replace(/^\/+/, ''); // 移除用户输入开头的斜杠

          const fullPath = cleanUserInput ? `/${cleanPrefix}/${cleanUserInput}` : `/${cleanPrefix}`;

          // 将完整路径写入YAML的fullPath字段
          setValueByPath(result, field.fullPath, fullPath);

          // 不需要将userInput和prefix写入YAML（它们只在表单中存在）
        }
        // 特殊处理动态字段
        else if (field.type === 'keyvalue') {
          if (field.isArray) {
            // params 类型：数组形式的键值对
            // formData[field.path] 应该是 [{ key, value, paramType }, ...]
            setValueByPath(result, field.path, value);
          } else {
            // environments 类型：对象形式的键值对
            // formData[field.path] 应该是 { key1: value1, key2: value2, ... }
            setValueByPath(result, field.path, value);
          }
        }
        // 跳过split-path-input的辅助字段：prefixPath和userInput字段本身不写入YAML
        // 这些字段在split-path-input类型中已经合并处理了
        else if (field.type === 'split-path-input') {
          // split-path-input字段的path是userInput，已在上面处理，这里跳过
          // 不写入YAML
        }
        // 检查这个字段是否是某个split-path-input字段的prefixPath
        else if (fieldsConfig.some(g => g.fields.some(f => f.prefixPath === field.path))) {
          // 这是一个prefixPath字段，不写入YAML
        }
        else {
          setValueByPath(result, field.path, value);
        }
      }
    });
  });

  return result;
}

/**
 * 从 YAML 对象提取表单数据
 * @param {Object} yamlData - YAML 数据对象
 * @param {Array} fieldsConfig - 字段配置
 * @returns {Object} 表单数据
 */
export function extractFormData(yamlData, fieldsConfig) {
  const formData = {};

  fieldsConfig.forEach(group => {
    group.fields.forEach(field => {
      // 特殊处理split-path-input类型：从YAML中读取完整路径并拆分
      if (field.type === 'split-path-input' && field.fullPath && field.prefixPath) {
        const fullValue = getValueByPath(yamlData, field.fullPath);
        if (fullValue) {
          // 拆分 /{bucket_name}/{user_path} 格式
          // 移除开头的斜杠并分割
          const cleanPath = fullValue.replace(/^\//, '');
          const firstSlashIndex = cleanPath.indexOf('/');

          if (firstSlashIndex !== -1) {
            // 存在用户路径部分
            formData[field.prefixPath] = cleanPath.substring(0, firstSlashIndex);
            formData[field.path] = cleanPath.substring(firstSlashIndex + 1);
          } else {
            // 只有bucket_name，没有用户路径
            formData[field.prefixPath] = cleanPath;
            formData[field.path] = '';
          }
        } else {
          // 如果YAML中没有值，使用默认值
          formData[field.prefixPath] = '';
          formData[field.path] = field.defaultValue || '';
        }
      }
      // 跳过那些仅用于split-path-input的辅助字段
      // 这些字段有prefixPath或fullPath属性，但field.path本身不是这些路径
      else if (field.prefixPath && field.path === field.prefixPath) {
        // 这是prefixPath字段，跳过（由split-path-input处理）
      }
      else if (field.fullPath && field.path === field.fullPath) {
        // 这是fullPath字段，跳过（由split-path-input处理）
      }
      // 常规字段处理
      else {
        const value = getValueByPath(yamlData, field.path);

        if (value !== undefined) {
          // 特殊处理keyvalue类型：确保类型正确
          if (field.type === 'keyvalue') {
            if (field.isArray) {
              // params类型：必须是数组
              formData[field.path] = Array.isArray(value) ? value : [];
            } else {
              // environments类型：必须是对象且不是数组
              formData[field.path] = (value && typeof value === 'object' && !Array.isArray(value)) ? value : {};
            }
          } else {
            formData[field.path] = value;
          }
        } else if (field.defaultValue !== undefined) {
          formData[field.path] = field.defaultValue;
        } else if (field.type === 'keyvalue') {
          // keyvalue类型没有值时，初始化为空数组或空对象
          formData[field.path] = field.isArray ? [] : {};
        }
      }
    });
  });

  return formData;
}

/**
 * 验证表单数据
 * @param {Object} formData - 表单数据
 * @param {Array} fieldsConfig - 字段配置
 * @returns {Object} { valid: boolean, errors: { path: string, message: string }[] }
 */
export function validateFormData(formData, fieldsConfig) {
  const errors = [];

  fieldsConfig.forEach(group => {
    group.fields.forEach(field => {
      if (field.required) {
        const value = formData[field.path];

        if (value === undefined || value === null || value === '') {
          errors.push({
            path: field.path,
            message: `${field.label}为必填项`,
          });
        }
      }
    });
  });

  return {
    valid: errors.length === 0,
    errors,
  };
}

/**
 * 深度克隆对象
 * @param {*} obj - 要克隆的对象
 * @returns {*} 克隆后的对象
 */
export function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }

  if (obj instanceof Array) {
    return obj.map(item => deepClone(item));
  }

  if (obj instanceof Object) {
    const clonedObj = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        clonedObj[key] = deepClone(obj[key]);
      }
    }
    return clonedObj;
  }
}

/**
 * 比较两个对象是否相等
 * @param {*} obj1 - 对象1
 * @param {*} obj2 - 对象2
 * @returns {boolean} 是否相等
 */
export function isEqual(obj1, obj2) {
  if (obj1 === obj2) return true;

  if (obj1 == null || obj2 == null) return false;
  if (typeof obj1 !== typeof obj2) return false;

  if (typeof obj1 !== 'object') return obj1 === obj2;

  if (Array.isArray(obj1) !== Array.isArray(obj2)) return false;

  if (Array.isArray(obj1)) {
    if (obj1.length !== obj2.length) return false;
    return obj1.every((item, index) => isEqual(item, obj2[index]));
  }

  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length !== keys2.length) return false;

  return keys1.every(key => isEqual(obj1[key], obj2[key]));
}
